Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

feature/node/src/commonTest/kotlin/org/meshtastic/feature/node/metrics/MetricsViewModelTest.kt 492afbde5c98f3efdcd367ab2f13ef3665fe7388 (492afbde) Text, 19.42 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.node.metrics

Tff7b72import T7ee787app.cash.turbine.test
Tff7b72import T7ee787dev.mokkery.answering.calls
Tff7b72import T7ee787dev.mokkery.answering.returns
Tff7b72import T7ee787dev.mokkery.every
Tff7b72import T7ee787dev.mokkery.everySuspend
Tff7b72import T7ee787dev.mokkery.matcher.any
Tff7b72import T7ee787dev.mokkery.mock
Tff7b72import T7ee787dev.mokkery.verifySuspend
Tff7b72import T7ee787kotlinx.coroutines.Dispatchers
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.test.StandardTestDispatcher
Tff7b72import T7ee787kotlinx.coroutines.test.resetMain
Tff7b72import T7ee787kotlinx.coroutines.test.runCurrent
Tff7b72import T7ee787kotlinx.coroutines.test.runTest
Tff7b72import T7ee787kotlinx.coroutines.test.setMain
Tff7b72import T7ee787okio.Buffer
Tff7b72import T7ee787okio.BufferedSink
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.di.CoroutineDispatchers
Tff7b72import T7ee787org.meshtastic.core.repository.FileService
Tff7b72import T7ee787org.meshtastic.core.repository.MeshLogRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.TracerouteResponseProvider
Tff7b72import T7ee787org.meshtastic.core.repository.TracerouteSnapshotRepository
Tff7b72import T7ee787org.meshtastic.feature.node.detail.NodeDetailUiState
Tff7b72import T7ee787org.meshtastic.feature.node.detail.NodeRequestActions
Tff7b72import T7ee787org.meshtastic.feature.node.domain.usecase.GetNodeDetailsUseCase
Tff7b72import T7ee787org.meshtastic.feature.node.model.MetricsState
Tff7b72import T7ee787org.meshtastic.feature.node.model.TimeFrame
Tff7b72import T7ee787org.meshtastic.proto.DeviceMetrics
Tff7b72import T7ee787org.meshtastic.proto.EnvironmentMetrics
Tff7b72import T7ee787org.meshtastic.proto.LocalStats
Tff7b72import T7ee787org.meshtastic.proto.MeshPacket
Tff7b72import T7ee787org.meshtastic.proto.Position
Tff7b72import T7ee787org.meshtastic.proto.PowerMetrics
Tff7b72import T7ee787org.meshtastic.proto.Telemetry
Tff7b72import T7ee787kotlin.test.AfterTest
Tff7b72import T7ee787kotlin.test.BeforeTest
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertNotNull
Tff7b72import T7ee787kotlin.test.assertTrue

Tff7b72class T56d364MetricsViewModelTest Tb4b4b4{

Tff7b72private Tff7b72val Te6edf3testDispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3dispatchers Tff7b72= Te6edf3CoroutineDispatchersTb4b4b4(Te6edf3main Tff7b72= Te6edf3testDispatcherTb4b4b4, Te6edf3io Tff7b72= Te6edf3testDispatcherTb4b4b4, Te6edf3default Tff7b72= Te6edf3testDispatcherTb4b4b4)

Tff7b72private Tff7b72val Te6edf3meshLogRepositoryTb4b4b4: Te6edf3MeshLogRepository Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3tracerouteResponseProviderTb4b4b4: Te6edf3TracerouteResponseProvider Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepository Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3tracerouteSnapshotRepositoryTb4b4b4: Te6edf3TracerouteSnapshotRepository Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3nodeRequestActionsTb4b4b4: Te6edf3NodeRequestActions Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3alertManagerTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3uiTb4b4b4.Te6edf3utilTb4b4b4.Te6edf3AlertManager Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3getNodeDetailsUseCaseTb4b4b4: Te6edf3GetNodeDetailsUseCase Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3fileServiceTb4b4b4: Te6edf3FileService Tff7b72= Te6edf3mockTb4b4b4(Tb4b4b4)

Tff7b72private Tff7b72lateinit Tff7b72var Te6edf3viewModelTb4b4b4: Te6edf3MetricsViewModel

Tf0883e@BeforeTest
Tff7b72fun Td2a8ffsetUpTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3DispatchersTb4b4b4.Te6edf3setMainTb4b4b4(Te6edf3testDispatcherTb4b4b4)

T8b949e// Default setup for flows
Te6edf3every Tb4b4b4{ Te6edf3tracerouteResponseProviderTb4b4b4.Te6edf3tracerouteResponse Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeRequestActionsTb4b4b4.Te6edf3lastTracerouteTime Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeRequestActionsTb4b4b4.Te6edf3lastRequestNeighborTimes Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Te6edf3emptyMapTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3nodeRepositoryTb4b4b4.Te6edf3nodeDBbyNum Tb4b4b4} Te6edf3returns Te6edf3MutableStateFlowTb4b4b4(Te6edf3emptyMapTb4b4b4(Tb4b4b4)Tb4b4b4)

T8b949e// Mock the case where we get node details
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3flowOfTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Tb4b4b4)Tb4b4b4)

Te6edf3viewModel Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffcreateViewModelTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657Int Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tff7b72= Te6edf3MetricsViewModelTb4b4b4(
Te6edf3destNum Tff7b72= Te6edf3destNumTb4b4b4,
Te6edf3dispatchers Tff7b72= Te6edf3dispatchersTb4b4b4,
Te6edf3meshLogRepository Tff7b72= Te6edf3meshLogRepositoryTb4b4b4,
Te6edf3tracerouteResponseProvider Tff7b72= Te6edf3tracerouteResponseProviderTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3tracerouteSnapshotRepository Tff7b72= Te6edf3tracerouteSnapshotRepositoryTb4b4b4,
Te6edf3nodeRequestActions Tff7b72= Te6edf3nodeRequestActionsTb4b4b4,
Te6edf3alertManager Tff7b72= Te6edf3alertManagerTb4b4b4,
Te6edf3getNodeDetailsUseCase Tff7b72= Te6edf3getNodeDetailsUseCaseTb4b4b4,
Te6edf3fileService Tff7b72= Te6edf3fileServiceTb4b4b4,
Tb4b4b4)

Tf0883e@AfterTest
Tff7b72fun Td2a8fftearDownTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3DispatchersTb4b4b4.Te6edf3resetMainTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8fftestInitializationTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertNotNullTb4b4b4(Te6edf3viewModelTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`state reflects updates from getNodeDetailsUseCase`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3nodeDetailFlow Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Te6edf3MetricsStateTb4b4b4.Te6edf3EmptyTb4b4b4, Te6edf3awaitItemTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3newState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3isFahrenheit Tff7b72= Tff7b72trueTb4b4b4)
Te6edf3nodeDetailFlowTb4b4b4.Te6edf3value Tff7b72= Te6edf3NodeDetailUiStateTb4b4b4(Te6edf3metricsState Tff7b72= Te6edf3newStateTb4b4b4)

Te6edf3assertEqualsTb4b4b4(Te6edf3newStateTb4b4b4, Te6edf3awaitItemTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`availableTimeFrames filters based on oldest data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3commonTb4b4b4.Te6edf3utilTb4b4b4.Te6edf3nowSeconds

Tff7b72val Te6edf3nodeDetailFlow Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3availableTimeFramesTb4b4b4.Te6edf3test Tb4b4b4{
T8b949e// Skip initial values
Tff7b72var Te6edf3current Tff7b72= Te6edf3awaitItemTb4b4b4(Tb4b4b4)

T8b949e// Provide data from 2 hours ago (7200 seconds)
T8b949e// This should make ONE_HOUR available, but not TWENTY_FOUR_HOURS
Tff7b72val Te6edf3twoHoursAgo Tff7b72= Te6edf3now Tff7b72- T79c0ff7T79c0ff2T79c0ff0T79c0ff0
Te6edf3nodeDetailFlowTb4b4b4.Te6edf3value Tff7b72=
Te6edf3NodeDetailUiStateTb4b4b4(
Te6edf3node Tff7b72=
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3modelTb4b4b4.Te6edf3NodeTb4b4b4(Te6edf3num Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4, Te6edf3user Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3UserTb4b4b4(Te6edf3id Tff7b72= Ta5d6ff"Ta5d6ff!1234Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3environmentState Tff7b72=
Te6edf3EnvironmentMetricsStateTb4b4b4(Te6edf3environmentMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3TelemetryTb4b4b4(Te6edf3time Tff7b72= Te6edf3twoHoursAgoTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)

T8b949e// We might get multiple emissions as flows propagate
Te6edf3current Tff7b72= Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Tff7b72while Tb4b4b4(Te6edf3currentTb4b4b4.Te6edf3size Tff7b72=Tff7b72= Te6edf3TimeFrameTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3sizeTb4b4b4) Tb4b4b4{ T8b949e// Skip the initial "all" if it's still there
Te6edf3current Tff7b72= Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Tb4b4b4}

Te6edf3assertTrueTb4b4b4(Te6edf3currentTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3TimeFrameTb4b4b4.Te6edf3ONE_HOURTb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Tff7b72!Te6edf3currentTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3TimeFrameTb4b4b4.Te6edf3TWENTY_FOUR_HOURSTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffShould not contain 24h for 2h old dataTa5d6ff"Tb4b4b4)

T8b949e// Provide data from 8 days ago
Tff7b72val Te6edf3eightDaysAgo Tff7b72= Te6edf3now Tff7b72- Tb4b4b4(T79c0ff8 Tff7b72* T79c0ff2T79c0ff4 Tff7b72* T79c0ff3T79c0ff6T79c0ff0T79c0ff0Tb4b4b4)
Te6edf3nodeDetailFlowTb4b4b4.Te6edf3value Tff7b72=
Te6edf3NodeDetailUiStateTb4b4b4(
Te6edf3node Tff7b72=
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3modelTb4b4b4.Te6edf3NodeTb4b4b4(Te6edf3num Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4, Te6edf3user Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3UserTb4b4b4(Te6edf3id Tff7b72= Ta5d6ff"Ta5d6ff!1234Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3environmentState Tff7b72=
Te6edf3EnvironmentMetricsStateTb4b4b4(
Te6edf3environmentMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3TelemetryTb4b4b4(Te6edf3time Tff7b72= Te6edf3eightDaysAgoTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Te6edf3current Tff7b72= Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3currentTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3TimeFrameTb4b4b4.Te6edf3SEVEN_DAYSTb4b4b4)Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`savePositionCSV writes correct data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3testPosition Tff7b72=
Te6edf3PositionTb4b4b4(
Te6edf3latitude_i Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4T79c0ff5T79c0ff6T79c0ff7T79c0ff8T79c0ff9Tb4b4b4,
Te6edf3longitude_i Tff7b72= Tff7b72-T79c0ff9T79c0ff8T79c0ff7T79c0ff6T79c0ff5T79c0ff4T79c0ff3T79c0ff2T79c0ff1Tb4b4b4,
Te6edf3altitude Tff7b72= T79c0ff1T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3sats_in_view Tff7b72= T79c0ff5Tb4b4b4,
Te6edf3ground_speed Tff7b72= T79c0ff1T79c0ff0Tb4b4b4,
Te6edf3ground_track Tff7b72= T79c0ff1T79c0ff2T79c0ff3T79c0ff4T79c0ff5T79c0ff6Tb4b4b4,
Te6edf3time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3positionLogs Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3testPositionTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
T8b949e// Wait for state to be collected so it's not Empty when savePositionCSV is called
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4) T8b949e// Empty
Te6edf3awaitItemTb4b4b4(Tb4b4b4) T8b949e// with position

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3savePositionCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3testPositionTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fflatitudeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fflongitudeTa5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff12.3456789Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff-98.7654321Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff100Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff10Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff1.23Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`saveDeviceMetricsCSV writes correct data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3testTelemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(
Te6edf3time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3device_metrics Tff7b72=
Te6edf3DeviceMetricsTb4b4b4(
Te6edf3battery_level Tff7b72= T79c0ff8T79c0ff0Tb4b4b4,
Te6edf3voltage Tff7b72= T79c0ff4.1fTb4b4b4,
Te6edf3channel_utilization Tff7b72= T79c0ff1T79c0ff2.5fTb4b4b4,
Te6edf3air_util_tx Tff7b72= T79c0ff3.25fTb4b4b4,
Te6edf3uptime_seconds Tff7b72= T79c0ff3T79c0ff6T79c0ff0T79c0ff0Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3deviceMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Te6edf3awaitItemTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3saveDeviceMetricsCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(
Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffbatteryLevelTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffvoltageTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffchannelUtilizationTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffairUtilTxTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffuptimeSecondsTa5d6ff\"Ta5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff80Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff4.1Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff12.5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3.25Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3600Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`saveEnvironmentMetricsCSV writes correct data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3testTelemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(
Te6edf3time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3environment_metrics Tff7b72=
Te6edf3EnvironmentMetricsTb4b4b4(
Te6edf3temperature Tff7b72= T79c0ff2T79c0ff1.5fTb4b4b4,
Te6edf3relative_humidity Tff7b72= T79c0ff5T79c0ff5.5fTb4b4b4,
Te6edf3barometric_pressure Tff7b72= T79c0ff1T79c0ff0T79c0ff1T79c0ff3.25fTb4b4b4,
Te6edf3gas_resistance Tff7b72= T79c0ff1T79c0ff2.3fTb4b4b4,
Te6edf3iaq Tff7b72= T79c0ff4T79c0ff2Tb4b4b4,
Te6edf3wind_speed Tff7b72= T79c0ff5.5fTb4b4b4,
Te6edf3wind_direction Tff7b72= T79c0ff1T79c0ff8T79c0ff0Tb4b4b4,
Te6edf3soil_temperature Tff7b72= T79c0ff1T79c0ff8.75fTb4b4b4,
Te6edf3soil_moisture Tff7b72= T79c0ff6T79c0ff5Tb4b4b4,
Te6edf3one_wire_temperature_ch0 Tff7b72= T79c0ff1fTb4b4b4,
Te6edf3one_wire_temperature_ch1 Tff7b72= T79c0ff2fTb4b4b4,
Te6edf3one_wire_temperature_ch2 Tff7b72= T79c0ff3fTb4b4b4,
T8b949e// 0 V is a real reading on an unloaded ADC input, so it exports as 0.0, not empty.
Te6edf3adc_voltage_ch0 Tff7b72= T79c0ff3.3fTb4b4b4,
Te6edf3adc_voltage_ch1 Tff7b72= T79c0ff0fTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(
Te6edf3NodeDetailUiStateTb4b4b4(
Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3deviceMetrics Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3environmentState Tff7b72= Te6edf3EnvironmentMetricsStateTb4b4b4(Te6edf3environmentMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3saveEnvironmentMetricsCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(
Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftemperatureTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffrelativeHumidityTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffbarometricPressureTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffgasResistanceTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffiaqTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffwindSpeedTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffwindDirectionTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffsoilTemperatureTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffsoilMoistureTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp1Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp2Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp4Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp6Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp7Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffoneWireTemp8Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage1Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage2Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage4Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage6Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage7Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffadcVoltage8Ta5d6ff\"Ta5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(
Ta5d6ff"Ta5d6ff\"Ta5d6ff21.5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff55.5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff1013.25Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff12.3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff42Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff5.5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff180Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff18.75Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff65Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff1.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff2.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3.3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff0.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff\"Ta5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`saveSignalMetricsCSV writes correct data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3testPacket Tff7b72= Te6edf3MeshPacketTb4b4b4(Te6edf3rx_time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4, Te6edf3rx_rssi Tff7b72= Tff7b72-T79c0ff1T79c0ff0T79c0ff5Tb4b4b4, Te6edf3rx_snr Tff7b72= T79c0ff7.5fTb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3signalMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3testPacketTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Te6edf3awaitItemTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3saveSignalMetricsCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3testPacketTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffrssiTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffsnrTa5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff-105Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff7.5Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`saveLocalStatsCSV writes only provided visible data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3visibleTelemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(
Te6edf3time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3local_stats Tff7b72=
Te6edf3LocalStatsTb4b4b4(
Te6edf3noise_floor Tff7b72= Tff7b72-T79c0ff1T79c0ff1T79c0ff2Tb4b4b4,
Te6edf3uptime_seconds Tff7b72= T79c0ff3T79c0ff6T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3channel_utilization Tff7b72= T79c0ff1T79c0ff2.5fTb4b4b4,
Te6edf3air_util_tx Tff7b72= T79c0ff3.25fTb4b4b4,
Te6edf3num_packets_tx Tff7b72= T79c0ff2Tb4b4b4,
Te6edf3num_packets_rx Tff7b72= T79c0ff3Tb4b4b4,
Te6edf3num_packets_rx_bad Tff7b72= T79c0ff1Tb4b4b4,
Te6edf3num_rx_dupe Tff7b72= T79c0ff4Tb4b4b4,
Te6edf3num_tx_relay Tff7b72= T79c0ff5Tb4b4b4,
Te6edf3num_tx_relay_canceled Tff7b72= T79c0ff6Tb4b4b4,
Te6edf3num_online_nodes Tff7b72= T79c0ff7Tb4b4b4,
Te6edf3num_total_nodes Tff7b72= T79c0ff8Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3hiddenTelemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(Te6edf3time Tff7b72= T79c0ff1T79c0ff6T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4, Te6edf3local_stats Tff7b72= Te6edf3LocalStatsTb4b4b4(Te6edf3noise_floor Tff7b72= Tff7b72-T79c0ff9T79c0ff9Tb4b4b4, Te6edf3uptime_seconds Tff7b72= T79c0ff1T79c0ff0Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(
Te6edf3NodeDetailUiStateTb4b4b4(
Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3localStats Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3visibleTelemetryTb4b4b4, Te6edf3hiddenTelemetryTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Te6edf3awaitItemTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3saveLocalStatsCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3visibleTelemetryTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffnoise_floor_dbmTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffuptime_secondsTa5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff-112Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3600Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff12.5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3.25Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff2Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff1Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff4Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff5Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff6Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff7Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff8Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Tff7b72!Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff-99Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffShould only export the rows supplied by the screenTa5d6ff"Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`clearLocalStats deletes local stats logs for route node`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Te6edf3everySuspend Tb4b4b4{ Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteLocalStatsLogsTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Tffa657Unit

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3clearLocalStatsTb4b4b4(Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3meshLogRepositoryTb4b4b4.Te6edf3deleteLocalStatsLogsTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4}
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`savePowerMetricsCSV writes correct data`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTestTb4b4b4(Te6edf3testDispatcherTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3testTelemetry Tff7b72=
Te6edf3TelemetryTb4b4b4(
Te6edf3time Tff7b72= T79c0ff1T79c0ff7T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tb4b4b4,
Te6edf3power_metrics Tff7b72=
Te6edf3PowerMetricsTb4b4b4(
Te6edf3ch1_voltage Tff7b72= T79c0ff3.3fTb4b4b4,
Te6edf3ch1_current Tff7b72= T79c0ff0.1fTb4b4b4,
Te6edf3ch2_voltage Tff7b72= T79c0ff5.0fTb4b4b4,
Te6edf3ch2_current Tff7b72= T79c0ff0.2fTb4b4b4,
Te6edf3ch3_voltage Tff7b72= T79c0ff1T79c0ff2.0fTb4b4b4,
Te6edf3ch3_current Tff7b72= T79c0ff0.3fTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3nodeDetailFlow Tff7b72=
Te6edf3MutableStateFlowTb4b4b4(Te6edf3NodeDetailUiStateTb4b4b4(Te6edf3metricsState Tff7b72= Te6edf3MetricsStateTb4b4b4(Te6edf3powerMetrics Tff7b72= Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3every Tb4b4b4{ Te6edf3getNodeDetailsUseCaseTb4b4b4(T79c0ff1T79c0ff2T79c0ff3T79c0ff4Tb4b4b4) Tb4b4b4} Te6edf3returns Te6edf3nodeDetailFlowTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3buffer Tff7b72= Te6edf3BufferTb4b4b4(Tb4b4b4)
Te6edf3everySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4} Te6edf3calls
Tb4b4b4{ Te6edf3args Tff7b72-Tff7b72>
Tff7b72val Te6edf3block Tff7b72= Te6edf3argsTb4b4b4.Te6edf3argTff7b72<Te6edf3suspend Tb4b4b4(Te6edf3BufferedSinkTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72>Tb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3blockTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72val Te6edf3vm Tff7b72= Te6edf3createViewModelTb4b4b4(Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3test Tb4b4b4{
Te6edf3awaitItemTb4b4b4(Tb4b4b4)
Te6edf3awaitItemTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6ffcontent://testTa5d6ff"Tb4b4b4)
Te6edf3vmTb4b4b4.Te6edf3savePowerMetricsCSVTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3listOfTb4b4b4(Te6edf3testTelemetryTb4b4b4)Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3verifySuspend Tb4b4b4{ Te6edf3fileServiceTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3anyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3csvOutput Tff7b72= Te6edf3bufferTb4b4b4.Te6edf3readUtf8Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3csvOutputTb4b4b4.Te6edf3startsWithTb4b4b4(
Ta5d6ff"Ta5d6ff\"Ta5d6ffdateTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6fftimeTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch1VoltageTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch1CurrentTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch2VoltageTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch2CurrentTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch3VoltageTa5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ffch3CurrentTa5d6ff\"Ta5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3csvOutputTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ff\"Ta5d6ff3.3Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff0.1Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff5.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff0.2Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff12.0Ta5d6ff\"Ta5d6ff,Ta5d6ff\"Ta5d6ff0.3Ta5d6ff\"Ta5d6ff"Tb4b4b4)Tb4b4b4)

Te6edf3cancelAndIgnoreRemainingEventsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.4.2 - Generated in 0.25s